// Include Files
#include "Definitions.h"

/////////////////////////////////////////////////////////////////////////////////////
// CEvent Template Implementation
template< class eventarg_t >
void IE::CEvent<eventarg_t>::Raise( eventarg_t *_pArg )
{
	// increase the argument ref count
	_pArg->AddRef();

	// raise the event in all the registrations
	m_RegMutex.Lock();
	uint_t uRegCount = m_lstRegs.GetSize();
	for( uint_t i = 0; i < uRegCount; ++i )
	{
		ABCRegistration *pReg = m_lstRegs[i];
		if( pReg ) pReg->Raise(_pArg);
	}
	m_RegMutex.Unlock();

	// decrease the argument ref count
	_pArg->Release();
}

template< class eventarg_t >
template< class listener_t >
void IE::CEvent<eventarg_t>::AddRegistration( 
	listener_t *_pListener, void (listener_t::*_pHandler)(eventarg_t &) )
{
	// create a new registration
	ABCRegistration *pReg = 
		new CRegistration<listener_t, eventarg_t>( _pListener, _pHandler );

	// search for an empty slot to insert the registration
	m_RegMutex.Lock();
	uint_t uRegCount = m_lstRegs.GetSize();
	for( uint_t i = 0; i < uRegCount; ++i )
	{
		if( !m_lstRegs[i] )
		{
			// found an empty slot
			m_lstRegs[i] = pReg;
			m_RegMutex.Unlock();
			return;
		}
	}

	// there was no empty slot, append the registration
	m_lstRegs.Append(pReg);
	m_RegMutex.Unlock();
}

template< class eventarg_t >
template< class listener_t >
void IE::CEvent<eventarg_t>::RemoveRegistration( 
	listener_t *_pListener, void (listener_t::*_pHandler)(eventarg_t &) )
{
	// search through the list backwards for a matching registration
	m_RegMutex.Lock();
	uint_t uRegCount = m_lstRegs.GetSize();
	for( uint_t i = uRegCount - 1; i >= 0; --i )
	{
		CRegistration<listener_t, eventarg_t> *pReg = 
			dynamic_cast< CRegistration<listener_t, eventarg_t> * >(m_lstRegs[i]);
		if( pReg && 
			pReg->GetListener() == _pListener && 
			pReg->GetHandler() == _pHandler )
		{
			// found the registration
			delete m_lstRegs[i];
			m_lstRegs[i] = CE_NULL;
			m_RegMutex.Unlock();
			return;
		}
	}

	// the registration was not in the list
	m_RegMutex.Unlock();
	assert(false);
}
